﻿using Idenmpotency;
using Microsoft.AspNetCore.Idenmpotency.AspNetCore.Impl;

namespace Microsoft.AspNetCore.Idenmpotency
{
    /// <summary>
    /// 幂等性中间件建造器（建造者模式）
    /// </summary>
    public class AspIdenmpotencyBuilder
    {
        /// <summary>
        /// 是否建造完成
        /// </summary>
        public bool IsBuilt { get; private set; }
        /// <summary>
        /// DI容器
        /// </summary>
        IServiceCollection _services = null;

        /// <summary>
        /// 暴露DI方便其他应用扩展
        /// </summary>
        /// <returns></returns>
        public IServiceCollection GetServiceCollection=> _services;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="services"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public AspIdenmpotencyBuilder(IServiceCollection services)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            this._services = services;
            _services.AddSingleton<IIdenmptencyRequestHandler, AspIdenmpotencyRequestHandler>();

        }
        /// <summary>
        /// 注册幂等性请求记录的仓储
        /// </summary>
        /// <typeparam name="TRepository"></typeparam>
        /// <returns></returns>
        public AspIdenmpotencyBuilder UseRepository<TRepository>()
            where TRepository : class, IIdenmpotencyRequestRepositroy
        {
            _services.AddSingleton<IIdenmpotencyRequestRepositroy, TRepository>();
            return this;
        }
        /// <summary>
        /// 注册幂等性请求类型
        /// </summary>
        /// <typeparam name="TAspIdenmpotencyRequest"></typeparam>
        /// <returns></returns>
        public AspIdenmpotencyBuilder ResiterRequestFactory<TFactory>()
               where TFactory : class, IAspIdenmpotencyRequestFactory
        {
            _services.AddSingleton<IAspIdenmpotencyRequestFactory, TFactory>();
            return this;
        }
        /// <summary>
        /// 注册幂等性检查处理器
        /// </summary>
        /// <typeparam name="THandler"></typeparam>
        /// <returns></returns>
        public AspIdenmpotencyBuilder ResiterHandler<THandler>()
            where THandler : class, IAspIdenmptencyRequestHandler
        {
            _services.AddSingleton<IAspIdenmptencyRequestHandler, THandler>();
            return this;
        }
        /// <summary>
        /// 是否注册异常检测
        /// </summary>
        /// <typeparam name="TItem"></typeparam>
        /// <exception cref="IdenmpotencyException"></exception>
        private void IsRegister<TItem>()
        {
            var result = _services
                .Where(sd => sd.ServiceType == typeof(TItem))
                .Any();
            if (!result)
            {
                throw new IdenmpotencyException($"{typeof(TItem)}实例未注册");
            }
        }
        /// <summary>
        /// 建造
        /// </summary>
        public void Build()
        {
            try
            {
                IsRegister<IIdenmpotencyRequestRepositroy>();
                IsRegister<IAspIdenmptencyRequestHandler>();
                IsRegister<IAspIdenmpotencyRequestFactory>();
            }
            catch (IdenmpotencyException e)
            {
                throw e;
            }
            _services.AddSingleton<IIdenmpotencyRequestHandlerFactroy, DefaultIdenmpotencyRequestHandlerFactroy>();
            _services.AddSingleton<IIdenmpotencyChecker, DefultIdenmpotencyChecker>();
            IsBuilt = true;
        }
    }
}
